/**
 * @UiBase.cpp
 * Copyright 2013 (C) FatalEror / Dean Bahari
 * 
 * UiPack is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 * 
 * See LICENSE file in main folder for more information.
 */

#include "UiCommon.hpp"
#include "UiApp.hpp"
#include "UiBase.hpp"
#include "UiButton.hpp"
#include "UiControl.hpp"
#include "UiEvent.hpp"
#include "UiResource.hpp"
#include "UiSizer.hpp"

unsigned int UiBase::currentID = 1000;
std::vector<UiBase*> UiBase::baseItem;
UiBase::UiBase(const wchar_t *name, UiBase *parent)
{
	mID      = UiBase::currentID++;
	mPosX    = 0;
	mPosY    = 0;
	mWidth   = 0;
	mHeight  = 0;
	mBkColor = UiResource::UI_BRUSH_BACKGROUND;
	mParent  = parent;
	mSizer   = NULL;
	mName    = name;

	mHandle = CreateWindow(L"UiBase", mName, WS_CLIPCHILDREN | WS_CLIPSIBLINGS, CW_USEDEFAULT, CW_USEDEFAULT, 1, 1, mParent ? mParent->getHandle() : NULL, 0, GetModuleHandle(0), this);
	if (mParent)
		mParent->addChild(this);
	baseItem.push_back(this);
}

UiBase::~UiBase()
{
}

void UiBase::close()
{
	DestroyWindow(this->getHandle());
}

void UiBase::setHandle(HWND newHandle)
{
	mHandle = newHandle;
}

void UiBase::setPosition(int x, int y)
{
	mPosX = x;
	mPosY = y;
	SetWindowPos(this->getHandle(), NULL, mPosX, mPosY, 0, 0, SWP_NOSIZE | SWP_NOZORDER | SWP_NOREDRAW);
}

void UiBase::setPosition(POINT pt)
{
	mPosX = pt.x;
	mPosY = pt.y;
	if (this->getHandle())
		SetWindowPos(this->getHandle(), NULL, mPosX, mPosY, 0, 0, SWP_NOSIZE | SWP_NOZORDER | SWP_NOREDRAW);
}

void UiBase::setSize(unsigned int width, unsigned int height)
{
	mWidth  = width;
	mHeight = height;
	if (this->getHandle())
		SetWindowPos(this->getHandle(), NULL, 0, 0, mWidth, mHeight, SWP_NOMOVE | SWP_NOZORDER);
}

void UiBase::setParent(UiBase *parent)
{
	mParent = parent;
	if (this->getHandle()) {
		SetWindowLong(this->getHandle(), GWL_STYLE, (GetWindowLong(this->getHandle(), GWL_STYLE) | WS_CHILD) & ~(WS_CAPTION | WS_THICKFRAME));
		SetParent(this->getHandle(), mParent->getHandle());
	}
}

void UiBase::setSizer(UiSizer *sizer)
{
	mSizer = sizer;
}

void UiBase::addChild(UiBase *child)
{
	child->setParent(this);
	mChild.push_back(child);
}

void UiBase::addControl(UiControl *control, int width, int height, int x, int y)
{
	this->addChild(control);
	control->setPosition(x, y);
	control->setSize(width, height);

	ShowWindow(control->getHandle(), SW_SHOWDEFAULT);
}

unsigned int UiBase::getID()
{
	return mID;
}

POINT UiBase::getPosition()
{
	POINT pt;
	pt.x = mPosX;
	pt.y = mPosY;
	return pt;
}

int UiBase::getWidth()
{
	return mWidth;
}

int UiBase::getHeight()
{
	return mHeight;
}

unsigned int UiBase::getBkColor()
{
	return mBkColor;
}

HWND UiBase::getHandle()
{
	return mHandle;
}

UiBase *UiBase::getParent()
{
	return mParent;
}

const wchar_t *UiBase::getName()
{
	return mName;
}

UiSizer *UiBase::getSizer()
{
	return mSizer;
}

unsigned int UiBase::getChildCount()
{
	return mChild.size();
}

LRESULT CALLBACK UiBase::handleCustomProc(UINT msg, WPARAM wParam, LPARAM lParam)
{
	return DefWindowProc(this->getHandle(), msg, wParam, lParam);
}

LRESULT CALLBACK UiBase::handleWindowProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
	UiBase *base = NULL;
	if (msg == WM_NCCREATE) {
		base = reinterpret_cast<UiBase*>(reinterpret_cast<LPCREATESTRUCT>(lParam)->lpCreateParams);
		if (base) {
			base->mHandle = hWnd;
			SetWindowLongPtr(base->mHandle, GWLP_USERDATA, reinterpret_cast<LONG>(base));
		}
	}

	base = reinterpret_cast<UiBase*>(GetWindowLongPtr(hWnd, GWLP_USERDATA));
	if (base) {
		if (msg == WM_NCDESTROY) {
			std::vector<UiBase*>::iterator it;
			for (it = baseItem.begin(); it != baseItem.end(); it++) {
				if ((*it) == base) {
					SetWindowLongPtr(base->mHandle, GWLP_USERDATA, NULL);
					delete (*it);
					baseItem.erase(it);
					break;
				}
			}
			if (baseItem.size() == 0)
				PostQuitMessage(0);
		} else
			return base->handleCustomProc(msg, wParam, lParam);
	}

	return DefWindowProc(hWnd, msg, wParam, lParam);
}